﻿//Game Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using Domain.Concrete;
using Pro260Website.Infrastructure;
using Pro260Website.Models;
using Domain.Abstract;
using Domain.Entity;

namespace Pro260Website.Controllers
{
    public class GameController : Controller
    {
        private readonly IGameRepository _gameRepository;
        private readonly IAccountRepository _accountRepository;
        private readonly IMetaScoreRepository _metaRepository;

        public GameController(IGameRepository gameRepository, IAccountRepository accountRepository,
                              IMetaScoreRepository metaRepository)
        {
            EFDbContext mainContext = EFDbContext.Instance;
            this._gameRepository = gameRepository;
            this._gameRepository.Context = mainContext;
            _accountRepository = accountRepository;
            this._accountRepository.Context = mainContext;
            _metaRepository = metaRepository;
            this._metaRepository.Context = mainContext;
        }

        public ActionResult List(string searchFor, int page = 1, int startingNum= 1, int pageSize = 10, string view = "List")
        {
    
           var items = _gameRepository.Games;
           

            if (!string.IsNullOrWhiteSpace(searchFor))
            {
                items =
                    items.Select(g => g).Where(g => g.Name.ToLower().Contains(searchFor.ToLower())).OrderBy(g => g.Id);
            }

            var pageCount = (int)Math.Ceiling((decimal)items.Count() / pageSize);

            var viewModel = new SliderListingModel
            {
                Items = new SliderImageModel
                {
                    Games = items.OrderBy(g => g.Id).Skip((page - 1) * pageSize).Take(pageSize), 
                    CurrentPageNumber = page,
                    NextPageNumber = page + 1 >= pageCount ? 1 : page + 1,
                    PreviousPageNumber = page - 1 <= 0 ? pageCount : page - 1,
                    TotalPageCount = pageCount,
                    StartingItem =  startingNum == 2 ? items.Count() + 1 : 1,
                    GameAjaxOptions = new AjaxOptions()
                                          {
                                              HttpMethod = "Get",
                                              UpdateTargetId = "gameUpdateItem",
                                              OnSuccess = "adjustHeight"
                                          }
                },
                QueryInfo = new QueryInfo
                {
                    QueryString = searchFor
                }
            };

            return View(view, viewModel);
        }
      

        public ActionResult ListUpcoming(int page = 1, int pageSize = 10)
        {
            var items = _gameRepository.Games.Where(g => g.ReleaseDate > DateTime.Now);

            var viewModel = new ListingViewModel<Game>
            {
                Items = items,
                PagingInfo = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = pageSize,
                    TotalItems = items.Count()
                },
                QueryInfo = new QueryInfo
                {
                    QueryString = ""
                }
            };

            return View(viewModel);
        }


        public ViewResult GamesList(int page = 1, int pageSize = 10, string viewName = "GameList",string title = "", string searchFor = "", GameViewType type = GameViewType.Games)
        {
            var items = _gameRepository.Games.GenerateList(type).Skip((page - 1) * pageSize).Take(pageSize);
            var viewModel = new ListingViewModel<Game>
            {
                Items = items,
                Title = title,
                ViewTypeEnum = (int) type,
                PagingInfo = new PagingInfo
                {
                    CurrentPage = page,
                    ItemsPerPage = pageSize,
                    TotalItems = items.Count()
                },
                QueryInfo = new QueryInfo
                {
                    QueryString = searchFor
                }
            };

            return View(viewName, viewModel);
        }

        public ActionResult Game(int id, string viewname = "Game")
        {
            var game = _gameRepository.Games.SingleOrDefault(g => g.Id == id);
            var account = _accountRepository.FindAccountByUsername(User.Identity.Name);

           var metascores = _metaRepository.FindScoresByGameId(id);

            foreach(var m in metascores)
            {
                game.MetaScores.Add(m);
            }

            if (account != null)
            {
                if (account.GameViewHistory.SingleOrDefault(g => g.Id == game.Id) == null)
                    account.GameViewHistory.Add(game);
                    _accountRepository.SaveAccount(account);
            }
            return View(viewname, game);
        }

        [Authorize]
        public void Rate(int rating, int gameId)
        {
            ViewBag.Rating = rating;
            var game = _gameRepository.FindById(gameId);
            game.NumRatings += 1;
            game.TotalRating += rating;
            _gameRepository.Save(game);

            Response.Write("You have rated the game " + rating + " star(s)");
        }

        public ActionResult TopRatedGames(int? year, string genre)
        {
            var games = _gameRepository.Games;

            ViewBag.Genres = _gameRepository.Games.Select(g => g.Genre).Distinct();
            ViewBag.Years = _gameRepository.Games.Where(g => g.ReleaseDate.Year > 1).Select(g => g.ReleaseDate.Year).Distinct();

            if (!string.IsNullOrEmpty(genre) && genre != "any")
                games = games.Where(g => g.Genre == genre);
            if (year != null)
                games = games.Where(g => g.ReleaseDate.Year == year);

            games = games.OrderByDescending(g => g.AverageRating).Take(5);

            return View(new ListingViewModel<Game>
            {
                Items = games
            });
        }

        public ActionResult ViewRequirements(int gameId)
        {
            var game = _gameRepository.Games.Single(g => g.Id == gameId);
            return View(game);
        }

        public FileContentResult GetDisplayImage(int id, int index)
        {
            var game = _gameRepository.FindById(id);
            if (game != null)
            {
                if (game.Pictures.Count - 1 >= index)
                {
                    var picture = game.Pictures.ElementAt(index);
                    if (picture != null)
                        return File(picture.ImageData, picture.ImageMimeType);
                }
            }

            return null;
        }

        public ActionResult ShowHistory(int page = 1, int pageSize = 3)
        {
            var account = _accountRepository.FindAccountByUsername(User.Identity.Name);

            var model = new ListingViewModel<Game>();
            if (account != null)
            {
                model.Items = account.GameViewHistory.Reverse();
                model.PagingInfo = new PagingInfo
                   {
                       CurrentPage = page,
                       ItemsPerPage = pageSize,
                       TotalItems = model.Items.Count()
                   };
            }

            return View(model);
        }
        public ActionResult ClearHistory()
        {
            var account = _accountRepository.FindAccountByUsername(User.Identity.Name);

            if (account != null)
            {
                account.GameViewHistory.Clear();
                _accountRepository.SaveAccount(account);
            }
            return RedirectToAction("ShowHistory");
        }

        public ActionResult ShowSuggestions(int page = 1, int pageSize = 10)
        {
            IEnumerable<Game> items = _gameRepository.Games;
            var account = _accountRepository.FindAccountByUsername(User.Identity.Name);

            if (account != null)
                items = items.Where(g => account.GameViewHistory.Select(a => a.Genre).Contains(g.Genre) &&
                      !account.GameViewHistory.Contains(g));
            else
                items = null;


            var model = new ListingViewModel<Game>
            {
                Items = items,
                PagingInfo = new PagingInfo()
                {
                    CurrentPage = page,
                    ItemsPerPage = pageSize,
                    TotalItems = items.Count()
                }
            };
            return View(model);
        }

        public PartialViewResult GetHints(string searchFor = "")
        {
            var games = _gameRepository.Games.Select(g => g.Name).Where(s => s.ToLower().Contains(searchFor.ToLower()) || searchFor == "");

            return PartialView(games);
        }

        public PartialViewResult GameOfTheWeek(string viewName = "GameOfTheWeek")
        {
            var game = _gameRepository.Games.FirstOrDefault(g => g.GameOftheWeekDate != null);

            if (game != null)
            {
                DateTime date = (DateTime)game.GameOftheWeekDate;
                if (date.AddDays(7).CompareTo(DateTime.Now) < 0)
                {
                    game.GameOftheWeekDate = null;
                    _gameRepository.Save(game);
                    int randomId = new Random().Next(_gameRepository.Games.Count()) + 1;
                    game = _gameRepository.Games.SingleOrDefault(g => g.Id == randomId);
                    game.GameOftheWeekDate = DateTime.Now;
                    _gameRepository.Save(game);
                }
            }
            else
            {
                int randomId = new Random().Next(_gameRepository.Games.Count() -1) + 1;
                game = _gameRepository.Games.SingleOrDefault(g => g.Id == randomId);
                game.GameOftheWeekDate = DateTime.Now;
                _gameRepository.Save(game);
            }


            return PartialView(viewName, game);
        }
    }
}
